/******************************************************************************************************
Copyright (C) 2013 Mestrelab Research S.L. All rights reserved.

This file is part of the MNova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*****************************************************************************************************/

/*globals qsTr, settings, Dialog, Dir, GroupBox, LineEdit, ToolButton, ComboBox, CommonSlots, FileDialog, MessageBox, serialization, Application, MnUi, CheckBox*/
/*jslint plusplus: true, indent: 4*/

function multiOpen() {
	"use strict";

	var gbMain, cbDirectory, tbOpenDir, cbFileMask, gbOpt, cbDirectory2, tbOpenDir2, cbFileMask2, dirName, dirName2,
		dir, dir2, mainFiles, optFiles, allFiles, i, oldFileHistory, cbOptDocs, docsToMerge = [], aDoc,
		main = {}, optional = {},
		itemsKey = "Multi Open/Items",
		optionalItemsKey = "Multi Open/Optional Items",
		optFilesKey = "Multi Open/Optional Files",
		optMultiDocsKey = "Multi Open/Mnova Multidocs Open",
		generalMasksKey = "Multi Open/General Masks",
		dialog = new Dialog(),
		msgDirNotExist = qsTr("Directory {0} does not exist."),
		openDirClicked = function () {
			var dirNameAux = this.currentText;
			dirNameAux = FileDialog.getExistingDirectory(dirNameAux);
			if (dirNameAux) {
				this.setEditText(dirNameAux);
			}
		};

	function getFirstTenPositions(structure) {
		var ii, newStructure = {};
		for (ii in structure) {
			if (structure.hasOwnProperty(ii)) {
				if (structure[ii].position < 10) {
					newStructure[ii] = structure[ii];
				}
			}
		}
		return newStructure;
	}


	function addValueToGeneralList(aValue) {

		var ii, currentList;

		if (aValue) {
			currentList = settings.value(generalMasksKey, "");
			currentList = currentList.split(",");
			if (currentList.indexOf(aValue) !== -1) {
				currentList.splice(currentList.indexOf(aValue), 1);
			}
			currentList.push("");
			for (ii = currentList.length - 1; ii > 0; ii--) {
				currentList[ii] = currentList[ii - 1];
			}
			currentList[0] = aValue;

			currentList = currentList.slice(0, 10);
			settings.setValue(generalMasksKey, currentList.toString());
		}
	}

	function saveItemsToRegistry() {
		var str;

		str = JSON.stringify(getFirstTenPositions(main));
		settings.setValue(itemsKey, str);
		str = JSON.stringify(getFirstTenPositions(optional));
		settings.setValue(optionalItemsKey, str);
	}

	function loadItems() {

		var ii, items = [];

		try {
			main = JSON.parse(settings.value(itemsKey, "{}"));

			for (ii in main) {
				if (main.hasOwnProperty(ii)) {
					items[main[ii].position] = ii;
				}
			}

			cbDirectory.items = items;
			cbDirectory.setEditText(items[0] || Dir.home());
			if (main[cbDirectory.currentText]) {
				cbFileMask.items = main[cbDirectory.currentText].items;
			} else {
				cbFileMask.items = settings.value(generalMasksKey, "").split(",");
			}

			items = [];
			optional = JSON.parse(settings.value(optionalItemsKey, "{}"));
			for (ii in optional) {
				if (optional.hasOwnProperty(ii)) {
					items[optional[ii].position] = ii;
				}
			}

			cbDirectory2.items = items;
			cbDirectory2.setEditText(items[0] || Dir.home());
			if (optional[cbDirectory2.currentText]) {
				cbFileMask2.items = optional[cbDirectory2.currentText].items;
			} else {
				cbFileMask2.items = settings.value(generalMasksKey, "").split(",");
			}
		} catch (ignore) {}
	}

	function updateList(mainWidget, secondaryWidget, structure) {
		secondaryWidget.clear();
		secondaryWidget.setEditText("");
		if (structure[mainWidget.currentText]) {
			secondaryWidget.items = structure[mainWidget.currentText].items;
		} else {
			secondaryWidget.items = settings.value(generalMasksKey, "").split(",");
		}
	}

	function saveStructure(mainWidget, secondaryWidget, structure) {
		var ii, pos;

		if (mainWidget.currentText !== "") {

			if (!structure[mainWidget.currentText]) {
				pos = 11;
			} else {
				pos = structure[mainWidget.currentText].position;
			}

			for (ii in structure) {
				if (structure.hasOwnProperty(ii)) {
					if (structure[ii].position < pos) {
						structure[ii].position++;
					}
				}
			}
			structure[mainWidget.currentText] = {items: secondaryWidget.items, position: 0};
		}
	}

	function inItems(item, items) {
		var ii;

		for (ii = 0; ii < items.length; ii++) {
			if (items[ii] === item) {
				return ii;
			}
		}
		return -1;
	}

	function updateItems(widget) {

		var ii, len, items = [], position, newItems = [];
		position = inItems(widget.currentText, widget.items);
		items = widget.items;

		if (widget.currentText !== "") {

			if (position === -1) {
				len = Math.min(items.length, 9);
			} else {
				len = Math.min(position, 9);
			}
			for (ii = 10; ii > 0; ii--) {
				if (ii > len) {
					if (items[ii]) {
						newItems[ii] = items[ii];
					}
				} else {
					newItems[ii] = items[ii - 1];
				}
			}
			newItems[0] = widget.currentText;
			widget.clear();
			widget.items = newItems;
		}
	}

	function createNewDocByReusing() {
		var auxDocs, doc, k;

		auxDocs = Application.mainWindow.documents();
		if (auxDocs.length > 0) {
			for (k = 0; k < auxDocs.length; k++) {
				doc = -1;
				if (auxDocs[k].isValid() && auxDocs[k].itemCount() === 0) {
					doc = auxDocs[k];
					break;
				}
			}
			if (doc === undefined || doc === -1) {
				doc = Application.mainWindow.newDocument();
			}
		} else {
			doc = Application.mainWindow.newDocument();
		}
		return doc;
	}

	//Calling this function with an array of Mnova documents will append all of them to the current one. Available since 15372 revision related to issue #8864
	function appendDocument(aArray) {
		var i;

		for (i = 0; i < aArray.length; ++i) {
			serialization.open(aArray[i], "mnpag");
			Application.mainWindow.activeDocument.setCurPageIndex(Application.mainWindow.activeDocument.pageCount() - 1); //to append the new document at the end
		}
	}

	dialog.title = qsTr("Multi-Open");
	gbMain = new GroupBox();
	gbMain.title = qsTr("Main Files");
	dialog.add(gbMain);
	cbDirectory = new ComboBox();
	cbDirectory.editable = true;
	cbDirectory.label = qsTr("Base Directory:");
	tbOpenDir = new ToolButton();
	tbOpenDir.text = "...";
	tbOpenDir.clicked.connect(cbDirectory, openDirClicked);
	gbMain.add(cbDirectory, tbOpenDir);
	cbFileMask = new ComboBox();
	cbFileMask.label = qsTr("Path Mask:");
	cbFileMask.editable = true;
	cbFileMask.toolTip = qsTr("Examples:\nPRJ ??????/*.fid/*.mol\n/SMPL-*/10/pdata/1r");
	gbMain.add(cbFileMask);
	gbOpt = new GroupBox();
	gbOpt.title = qsTr("Optional Files");
	gbOpt.checkable = true;
	gbOpt.checked = settings.value(optFilesKey, false);
	dialog.add(gbOpt);
	cbDirectory2 = new ComboBox();
	cbDirectory2.label = qsTr("Base Directory:");
	cbDirectory2.editable = true;
	tbOpenDir2 = new ToolButton();
	tbOpenDir2.text = "...";
	tbOpenDir2.clicked.connect(cbDirectory2, openDirClicked);
	gbOpt.add(cbDirectory2, tbOpenDir2);
	cbFileMask2 = new ComboBox();
	cbFileMask2.label = qsTr("Path Mask:");
	cbFileMask2.editable = true;
	cbFileMask2.toolTip = qsTr("Examples:\nPRJ ??????/*.mol/fid\n/SMPL-*/10/pdata/*.mol");
	gbOpt.add(cbFileMask2);
	cbOptDocs = new CheckBox();
	cbOptDocs.text = qsTr("Open Mnova Files into a Single Document");
	cbOptDocs.checked = settings.value(optMultiDocsKey, false);
	cbOptDocs.toolTip = "<p align = justify>Check the option to open all the files in one document. Use this option to combine raw data and Mnova files in the same document.</p>";
	dialog.add(cbOptDocs);
	loadItems();

	cbDirectory.editTextChanged.connect(function () {

		updateList(cbDirectory, cbFileMask, main);
		saveStructure(cbDirectory, cbFileMask, main);
	});

	cbDirectory2.editTextChanged.connect(function () {

		updateList(cbDirectory2, cbFileMask2, optional);
		saveStructure(cbDirectory2, cbFileMask2, optional);
	});

	if (!dialog.exec()) {
		return;
	}

	dirName = cbDirectory.currentText;
	dir = new Dir(dirName);
	if (!dirName || !dir.exists) {
		MessageBox.critical(msgDirNotExist.format(dirName), MessageBox.Ok);
		return;
	}

	dirName2 = cbDirectory2.currentText;
	dir2 = new Dir(dirName2);
	if (gbOpt.checked && (!dirName2 || !dir2.exists)) {
		MessageBox.critical(msgDirNotExist.format(dirName2), MessageBox.Ok);
		return;
	}

	updateItems(cbFileMask);
	updateItems(cbFileMask2);
	saveStructure(cbDirectory, cbFileMask, main);
	saveStructure(cbDirectory2, cbFileMask2, optional);
	updateItems(cbDirectory);
	updateItems(cbDirectory2);
	saveItemsToRegistry();
	addValueToGeneralList(cbFileMask2.currentText);
	addValueToGeneralList(cbFileMask.currentText);

	settings.setValue(optFilesKey, gbOpt.checked);
	settings.setValue(optMultiDocsKey, cbOptDocs.checked);

	mainFiles = dir.entryListAdv(cbFileMask.currentText);
	mainFiles.sort(Dir.numericPathsCompare);

	if (!mainFiles.length) {
		MessageBox.warning(qsTr("No files matching to the specified main path mask found."), MessageBox.Ok);
		return;
	}

	optFiles = [];
	if (gbOpt.checked) {
		optFiles = dir2.entryListAdv(cbFileMask2.currentText);
		optFiles.sort(Dir.numericPathsCompare);
	}

	allFiles = [];
	for (i = 0; i < Math.max(mainFiles.length, optFiles.length); i++) {
		if (i < mainFiles.length) {
			allFiles.push(mainFiles[i]);
		}
		if (i < optFiles.length) {
			allFiles.push(optFiles[i]);
		}
	}

	oldFileHistory = serialization.fileHistory;
	serialization.fileHistory = false;

	//If is enabled the option to work in a single document. We create a new document for the result and we clone all pages to this document
	if (cbOptDocs.checked) {
		//Create the result doc if we coudn't reuse it because it is not blank
		aDoc = createNewDocByReusing();
		aDoc.deletePages(aDoc.pages());
		//For all mnova document
		for (i = 0; i < allFiles.length; i++) {
			if (allFiles[i].toString().toLowerCase().indexOf("mnova", allFiles[i].toString().length - "mnova".length) !== -1) {
				//We push it into the mnova stack paths
				docsToMerge = [];
				docsToMerge.push(allFiles[i]);
				appendDocument(docsToMerge);
			} else {
				serialization.open(allFiles[i]);
			}
		}
		//Set the result document to active and put the optional files at the end of the result document
		Application.mainWindow.activeDocument = aDoc;
	} else {
		//We open all files at once
		serialization.open(allFiles);
	}
	serialization.fileHistory = oldFileHistory;
}

if (this.MnUi && MnUi.scripts_common) {
	MnUi.scripts_common.scripts_common_MultiOpen = multiOpen;
}
